#ifndef PLOG_LOG_MESSAGE_H
#define PLOG_LOG_MESSAGE_H

#include <sstream>
#include <ctime>

#include <windows.h>
#include "plog/log_level.h"

namespace plog
{
    struct context_info
    {
        context_info(const char* filex, const char* func_namex, size_t linex, unsigned tidx, SYSTEMTIME* timex = NULL)
            : tid(tidx)
            , file(filex)
            , func_name(func_namex)
            , line(linex)
        {
            if (timex)
                time = *timex;
            else
                ::GetLocalTime(&time);
        }

        context_info()
            : tid(0)
            , file("")
            , func_name("")
            , line(0)
        {
            memset(&time, 0, sizeof(SYSTEMTIME));
        }

        SYSTEMTIME time;
        unsigned tid;
        const char* file;
        const char* func_name;
        size_t line;
    };

#define CONTEXT_INFO plog::context_info(__FILE__, __FUNCTION__, __LINE__, ::GetCurrentThreadId())

    //////////////////////////////////////////////////////////////////////////

    class message
    {
        friend bool operator==(const message& msg1, const message& msg2);

    public:
        message(log_level severity, const context_info& context, const char* message = "")
            : severity_(severity)
            , stream_(message)
            , context_(context)
        {
        }

        template<typename T>
        message& operator<< (const T& chunk)
        {
            stream_ << chunk;
            return *this;
        }

        std::string text() const
        {
            return stream_.str();
        }

        const char* severity_name() const
        {
            return level_name(severity_);
        }

        log_level severity() const
        {
            return severity_;
        }

        const context_info& context() const
        {
            return context_;
        }

    private:
        std::stringstream stream_;
        log_level severity_;
        context_info context_;
    };

    inline bool operator==(const message& msg1, const message& msg2)
    {
        if (msg1.severity_ == msg2.severity_ && msg1.stream_.str() == msg2.stream_.str())
            return true;
        else
            return false;
    }

    inline std::ostream& operator<< (std::ostream &stream, const message& msg)
    {
        stream << msg.severity_name() << ":" << msg.text();
        return stream;
    }
}



#endif